package ferp.core.player;

import ferp.core.game.Game;
import ferp.core.game.Input;
import ferp.core.game.Settings;

/**
 * User: olegs
 * Date: 19/05/11 15:12
 */
public abstract class Player
{
  // safely return player id
  public static int id(Player player) {return player == null ? Game.NO_ID : player.id();}
  public static boolean isHuman(int id) {return id == 0;}
  public static boolean isHuman(Player p) {return p.id() == 0;}

  public Player(int id, String name)
  {
    this.id = id;
    this.name  = name;
  }

  // get id
  public final int id() {return id;}
  // get name
  public String name() {return name;}

  // this actually checks if this player is a first hand in the current set
  public boolean isFirstHand(Game g)
  {
    return id == Game.next(g.player.dealer);
  }

  public abstract void reset(Game g);

  // set input options for different game modes
  public abstract int setBiddingInputOptions(Game g, Input.Options io);
  public abstract int setDroppingInputOptions(Game g, Settings settings, Input input, Input.Options io);
  public abstract int setStandInputOptions(Input.Options io);
  public abstract int setContractingInputOptions(Game g, Input.Options io);
  public abstract int setContractingInputOptionsCheck10(Input.Options io);
  public void setPassingInputOptions(Game.Listener listener, Game g) throws Game.Error {g.options.set(Input.Options.WAIT_FOR_RESOLVER);}
  public void setMisereInputOptions(Game.Listener listener, Game g) throws Game.Error {g.options.set(Input.Options.WAIT_FOR_RESOLVER);}
  public void setTrickingInputOptions(Game.Listener listener, Game g) throws Game.Error {g.options.set(Input.Options.WAIT_FOR_RESOLVER);}

  // todo: add more methods reflecting specific actions -> (bid, play card, drop, etc...)
  // bid - called in bidding mode
  public abstract void bid(Game.Listener listener, Game g, Settings settings, Input input);
  // contract - called in contracting mode
  public abstract void contract(Game g, Settings settings, Input input);
  // drop cards - implemented in Human
  public abstract void drop(Game g, Input input);
  // set game's type - called by opponent player
  public abstract void setGameType(Game g, Input input);
  // set 'check10' mode
  public abstract void setCheck10(Game g, Input input);

  @Override
  public String toString()
  {
    return name;
  }

  // reset data - called every time before new set starts
  protected final void reset(Game g, boolean open)
  {
    g.player.reset(id, open);
  }

  // whether player can say 'without 3'
  protected boolean canWithout3(Game g, Settings settings) {return !g.getDeclarerBid().current.isMisere() && settings.without3;}

  // player id, assigned by the Game object
  private int id;
  // player name, assigned by the Game object
  private String name;
}
